package com.xmhmyh.generalframework.project.systool.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xmhmyh.generalframework.common.BaseServiceImpl;
import com.xmhmyh.generalframework.common.constants.Constants;
import com.xmhmyh.generalframework.common.enums.ResponseCode;
import com.xmhmyh.generalframework.common.utils.*;
import com.xmhmyh.generalframework.framework.exceptions.ManageExceptions;
import com.xmhmyh.generalframework.framework.security.LoginUser;
import com.xmhmyh.generalframework.project.sys.entity.User;
import com.xmhmyh.generalframework.project.systool.dto.TableDTO;
import com.xmhmyh.generalframework.project.systool.entity.Table;
import com.xmhmyh.generalframework.project.systool.entity.TableColumn;
import com.xmhmyh.generalframework.project.systool.mapper.TableColumnMapper;
import com.xmhmyh.generalframework.project.systool.mapper.TableMapper;
import com.xmhmyh.generalframework.project.systool.service.ITableColumnService;
import com.xmhmyh.generalframework.project.systool.service.ITableService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author
 * @since
 */
@Service
@Slf4j
public class TableServiceImpl extends BaseServiceImpl<TableMapper, Table> implements ITableService {

    @Resource
    private TableColumnMapper tableColumnMapper;
    @Autowired
    private ITableColumnService tableColumnService;

    @Autowired
    private GenUtils genUtils;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importTableHandler(User user, List<TableDTO> tableDTOList) {
        for (TableDTO tableDTO : tableDTOList) {
            // 删除老的信息
            removeByTableName(tableDTO.getTableName());
            // 保存表信息
            Table table = new Table();
            table.setTableId(uidGenerator.getUID());
            table.setTableName(tableDTO.getTableName());
            table.setTableComment(tableDTO.getTableComment());
            MyBeanUtils.setSysInfo(table, user.getId(), user.getAccountId());
            genUtils.initTable(table);
            save(table);
            // 保存表的各列信息
            List<TableColumn> tableColumnList = tableColumnMapper.selectDbTableColumnsByName(tableDTO.getTableName());
            for (TableColumn tableColumn : tableColumnList) {
                MyBeanUtils.setSysInfo(tableColumn, user.getId(), user.getAccountId());
                tableColumn.setColumnId(uidGenerator.getUID());
                genUtils.initColumnField(tableColumn, table);
                tableColumnService.save(tableColumn);
            }
        }
    }


    /**
     * @Author: 于丁
     * @Description: 删除Table&TableColumn根据TabelName
     * @DateTime: 2020/8/6 11:11 上午
     * @Params:
     * @Return
     */
    public void removeByTableName(String tableName) {
        LambdaQueryWrapper<Table> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Table::getTableName, tableName);
        List<Table> tableList = list(lambdaQueryWrapper);
        for (Table table : tableList) {
            tableColumnService.removeByTableId(table.getTableId());
            removeById(table.getTableId());
        }
    }


    @Override
    public byte[] genHandler(Long tableId) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        generatorCode(tableId, zip);
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    @Override
    public Map<String, String> previewCode(Long tableId) {
        Map<String, String> dataMap = new LinkedHashMap<>();
        Table table = getById(tableId);
        if (table == null) {
            throw new ManageExceptions(ResponseCode.TABLE_NOT_FIND);
        }
        List<TableColumn> columns = tableColumnService.getByTableId(table.getTableId());
        table.setColumns(columns);
        setPkColumn(table, columns);


        VelocityContext context = VelocityUtils.getVelocityContext();

        VelocityUtils.initParams(context, table);

        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
        for (String template : templates) {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
            tpl.merge(context, sw);
            dataMap.put(template, sw.toString());
        }
        return dataMap;
    }

    @Override
    public void delHandler(Long tableId) {
        tableColumnService.removeByTableId(tableId);
        removeById(tableId);
    }

    /**
     * 设置主键列信息
     *
     * @param table   业务表信息
     * @param columns 业务字段列表
     */
    public void setPkColumn(Table table, List<TableColumn> columns) {
        for (TableColumn column : columns) {
            if (column.isPk()) {
                table.setPkColumn(column);
                break;
            }
        }
        if (StringUtils.isNull(table.getPkColumn())) {
            table.setPkColumn(columns.get(0));
        }
    }

    /**
     * 查询表信息并生成代码
     */
    private void generatorCode(Long tableId, ZipOutputStream zip) {

        Table table = getById(tableId);
        if (table == null) {
            throw new ManageExceptions(ResponseCode.TABLE_NOT_FIND);
        }
        List<TableColumn> columns = tableColumnService.getByTableId(table.getTableId());
        table.setColumns(columns);
        setPkColumn(table, columns);


        VelocityContext context = VelocityUtils.getVelocityContext();

        VelocityUtils.initParams(context, table);

        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
        for (String template : templates) {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
            tpl.merge(context, sw);
            try {
                // 添加到zip
                String fileName = VelocityUtils.getFileName(template, table);
                if (StringUtils.isBlank(fileName)) {
                    throw new IOException("未获取文件名");
                }
                zip.putNextEntry(new ZipEntry(fileName));
                IOUtils.write(sw.toString(), zip, Constants.UTF8);
                IOUtils.closeQuietly(sw);
                zip.flush();
                zip.closeEntry();
            } catch (IOException e) {
                log.error("渲染模板失败，表名：" + table.getTableName(), e);
            }
        }
    }
    //
//    @GetMapping("genCode")
//    public Response genCodeHandler(HttpServletResponse response) throws IOException, AWTException {
////        /**1、初始化输出流**/
////        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
////        ZipOutputStream zip = new ZipOutputStream(outputStream);
////        /**1、初始化模版引擎**/
////        VelocityContext context = VelocityUtils.getVelocityContext();
////        /**2、设置模版参数**/
////        VelocityUtils.putParams(context, "message", "测试消息");
////        /**3、设置模版**/
////        StringWriter sw = new StringWriter();
////        Template tpl = Velocity.getTemplate("vm/entity.java.vm", "UTF-8");
////        tpl.merge(context, sw);
////        System.out.println("导出的文档信息：" + sw.toString());
//        return Response.success();
////        /**3、导出**/
////        try {
////            // 添加到zip
////            zip.putNextEntry(new ZipEntry("code"));
////            IOUtils.write(sw.toString(), zip, "UTF-8");
////            IOUtils.closeQuietly(sw);
////            zip.flush();
////            zip.closeEntry();
////        } catch (IOException e) {
////            log.error("渲染模板失败：", e);
////        }
////        ServletUtils.outZip(response, outputStream, zip);
//    }
}
